#include "cfg_view.hpp"
#include "custom_controls.hpp"
#include "imgui/imgui_stdlib.h"
#include <sstream>

extern void HelperMaker(const char* desc, bool sameLine);

namespace ImGui {
#define D(T,N) void RenderCfg##T(Cfg##N *item)
    D(Group, Group) {
        bool enabled = item->Enabled();
        BeginDisabled(!enabled);
        bool open = !item->show_title_ || CollapsingHeader(item->title_.c_str(), enabled ? ImGuiTreeNodeFlags_DefaultOpen : 0);
        EndDisabled();
        if (!item->help_.empty() && IsItemHovered())
            SetTooltip("%s", item->help_.c_str());
        if (open) {
            if (item->show_title_)
                TreePush(item);
            for (auto &x: item->children_) {
                x->Render();
            }
            if (item->show_title_)
                TreePop();
        }
    }
    D(Text, Text) {
        BeginDisabled(!item->Enabled());
        TextUnformatted(item->title_.c_str());
        SameLine(GetFontSize() * 10.f);
        InputText(item->title_hidden_.c_str(), &item->vcache_);
        if (!item->help_.empty())
            ::HelperMaker(item->help_.c_str(), true);
        EndDisabled();
    }
    D(Integral, Integral) {
        BeginDisabled(!item->Enabled());
        TextUnformatted(item->title_.c_str());
        SameLine(GetFontSize() * 10.f);
        InputScalar(item->title_hidden_.c_str(), item->is_signed_ ? ImGuiDataType_S64 : ImGuiDataType_U64, &item->i64_);
        if (!item->help_.empty())
            ::HelperMaker(item->help_.c_str(), true);
        EndDisabled();
    }
    D(FloatingPoint, Real) {
        BeginDisabled(!item->Enabled());
        TextUnformatted(item->title_.c_str());
        SameLine(GetFontSize() * 10.f);
        InputDouble(item->title_hidden_.c_str(), &item->value_);
        if (!item->help_.empty())
            ::HelperMaker(item->help_.c_str(), true);
        EndDisabled();
    }
    D(Switch, Switch) {
        BeginDisabled(!item->Enabled());
        TextUnformatted(item->title_.c_str());
        SameLine(GetFontSize() * 10.f);
        Checkbox(item->title_hidden_.c_str(), &item->value_);
        if (!item->help_.empty())
            ::HelperMaker(item->help_.c_str(), true);
        EndDisabled();
    }
    D(Choice, Choice) {
        BeginDisabled(!item->Enabled());
        TextUnformatted(item->title_.c_str());
        SameLine(GetFontSize() * 10.f);
        if (BeginCombo(item->title_hidden_.c_str(), item->vcache_.c_str()))
        {
            for (int i=0; i<item->options_.size(); ++i) {
                if (Selectable(item->options_[i].c_str()))
                {
                    item->selected_ = i;
                    item->vcache_ = item->options_[i];
                }
                if (item->selected_ == i)
                    SetItemDefaultFocus();
            }
            EndCombo();
        }
        if (!item->help_.empty())
            ::HelperMaker(item->help_.c_str(), true);
        EndDisabled();
    }
    D(Action, Action) {
        if (item->sameline_)
            SameLine();
        BeginDisabled(!item->Enabled());
        if (Button(item->title_.c_str()))
            item->callback_();
        if (!item->help_.empty())
            ::HelperMaker(item->help_.c_str(), true);
        EndDisabled();
    }

    void RenderCfgItem(CfgItemBase *item) {
#define R(T,N) case CfgType::T: RenderCfg##T((Cfg##N*)item); break
        switch (item->type_)
        {
        R(Group,Group);
        R(Text,Text);
        R(Integral, Integral);
        R(FloatingPoint, Real);
        R(Switch, Switch);
        R(Choice, Choice);
        R(Action, Action);
        default: assert (0); // must not got here
        }
    }

    void RenderConfigView(CfgItemBase *cfg, ImVec2 area, bool as_popup)
    {
        struct _ {
            _() {
                CfgItemBase::pFnRender = RenderCfgItem;
            }
        } helper; // 配置渲染函数

        bool open = BeginChild(GetID(cfg), area, ImGuiChildFlags_FrameStyle, 0);
        if (open)
        {
            PushStyleColor(ImGuiCol_FrameBg, IM_COL32(0,0,0,255));
            if (cfg)
                cfg->Render();
            PopStyleColor(1);
        }
        if (as_popup) {
            static const char* texts[] = {
                " 保存",
                " 重置",
                " 取消",
            };
            WindowBottomButtons(3,texts,[](int idx, void *user){
                CfgItemBase *cfg = (CfgItemBase*)user;
                std::ostringstream oss;
                bool close = true;
                switch (idx)
                {
                case 0:
                    if (!cfg->Save(oss))
                    {
                        close = false;
                    }
                    break;
                case 1:
                    close = false;
                    [[fallthrough]];
                default:
                    cfg->Load();
                    break;
                }
                if (close)
                    CloseCurrentPopup();
            }, cfg);
        }
        EndChild();
    }
}

